package com.shopcart.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import com.shopcart.entity.Cart;
import com.shopcart.entity.CartItem;
import com.shopcart.entity.Customer;
import com.shopcart.entity.Product;

@Stateful(name = "CartControllerBean", mappedName = "ejb/CartControllerBean")
public class CartControllerBean implements CartController {
	@PersistenceContext
	private EntityManager em;
	private Cart cart = new Cart();
	private Customer customer;
	
	@Override
	public void createCart(List<Long> producIdList, List<Integer> productCountList, Integer size) {
		rollback();
		
		List<CartItem> cartItems = new ArrayList<CartItem>();
		
		for (int i = 0; i < size; i++) {
			CartItem cartItem = new CartItem();
			
			//get Product model
			Query query = em.createQuery("select p from Product p left join fetch p.matchingProducts where p.id=:id");
			query.setParameter("id", producIdList.get(i));
			Product product = (Product) query.getSingleResult();
			
			Integer orderedCount = productCountList.get(i);
			Integer availableQuantity = product.getQuantity();
			
			if (availableQuantity >= orderedCount) {
				product.setQuantity(availableQuantity - orderedCount);
				product = em.merge(product);
			} else {
				//TODO throw exception
				return;
			}
			
			//create cartItem
			cartItem.setProduct(product);
			cartItem.setCount(orderedCount);
			
			em.persist(cartItem);
			
			cartItems.add(cartItem);
		}
		
		getCart().setCustomer(getCustomer());
		getCart().setItems(cartItems);
		getCart().setDate(new Date());
		
		em.persist(cart);
		
		cart = new Cart();
	}
	
	@Override
	public void updateCart(List<Long> producIdList, List<Integer> productCountList, Integer size) {
		rollback();
		
		List<CartItem> cartItems = new ArrayList<CartItem>();
		
		for (int i = 0; i < size; i++) {
			CartItem cartItem = new CartItem();
			
			//get Product model
			Query query = em.createQuery("select p from Product p left join fetch p.matchingProducts where p.id=:id");
			query.setParameter("id", producIdList.get(i));
			Product product = (Product) query.getSingleResult();
			
			Integer orderedCount = productCountList.get(i);
			Integer availableQuantity = product.getQuantity();
			
			if (availableQuantity >= orderedCount) {
				product.setQuantity(availableQuantity - orderedCount);
				product = em.merge(product);
			} else {
				//TODO throw exception
				return;
			}
			
			//create cartItem
			cartItem.setProduct(product);
			cartItem.setCount(orderedCount);
			
			cartItems.add(cartItem);
		}
		
		getCart().setCustomer(getCustomer());
		getCart().setItems(cartItems);
		getCart().setDate(new Date());
	}
	
	public void rollback() {
		for (CartItem ci : cart.getItems()) {
			Integer itemCount = ci.getCount();
			Long productId = ci.getProduct().getId();
			
			Query query = em.createQuery("select p from Product p where p.id=:id");
			query.setParameter("id", productId);
			Product product = (Product) query.getSingleResult();
			
			product.setQuantity(product.getQuantity() + itemCount);
			
			em.persist(product);
		}
	}

	@Override
	public List<Cart> getCarts(Customer customer) {
		Query query = em.createQuery("select c from Cart c where c.customer=:customer");
		query.setParameter("customer", customer);
		
		return (List<Cart>) query.getResultList();
	}

	@Override
	public Customer getCustomer() {
		return customer;
	}

	@Override
	public void setCustomer(Customer customer) {
		this.customer = customer;
	}

	@Override
	public Cart getCart() {
		return cart;
	}

	@Override
	public void setCart(Cart cart) {
		this.cart = cart;
	}

	@Override
	@Remove
	public void remove() {
		cart = null;
	}
}